﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VupSlashLauncher.Common;
using VupSlashLauncher.View;

namespace VupSlashLauncher.Model
{

    public static class IFunc
    {
        public static void LoadConfigFile()
        {
            if (!Directory.Exists(GlobalValues.ConfigDir))
            {
                string olddir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\VupS";
                if (!Directory.Exists(olddir))
                    Directory.CreateDirectory(GlobalValues.ConfigDir);
                else Directory.Move(olddir, GlobalValues.ConfigDir);
            }
            if (!File.Exists(GlobalValues.ConfigFile))
            {
                GlobalValues.FirstTimeStart = true;
                File.Create(GlobalValues.ConfigFile).Close();
            }
            try
            {
                GlobalValues.GameDir = INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "GameDirectory", @".\");
                GlobalValues.PositionLeft = Convert.ToInt32(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "PositionLeft", "0"));
                GlobalValues.PositionTop = Convert.ToInt32(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "PositionTop", "0"));
                GlobalValues.ThemeColor = INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "ThemeColor", "#3D6CB4");
                GlobalValues.ThemeColorTitle = INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "ThemeColorTitle", "Normal");
                GlobalValues.UpdateUrl = INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "CheckUpdateUrl", GlobalValues.UpdateUrl);
                GlobalValues.NoticeLocal = INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "Notice", "Notice0");
                GlobalValues.CloseWhenStart = Convert.ToBoolean(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "CloseWhenStart", "false"));
                GlobalValues.StartShowNotice = Convert.ToBoolean(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "StartShowNotice", "true"));
                GlobalValues.AutoCheckLauncherUpdate = Convert.ToBoolean(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "AutoCheckLauncherUpdate", "true"));
                GlobalValues.DebugMode = Convert.ToBoolean(INIOperation.INIGetStringValue(GlobalValues.ConfigFile, "Vup", "Debug", "false"));
                GlobalValues.LocalVersion = INIOperation.INIGetStringValue(GlobalValues.GameDir + "\\version.ini", "Vup", "LocalVersion", "未知版本");
            }
            catch { }
            if (!Directory.Exists(GlobalValues.GameDir))
            {
                GlobalValues.GameDir = @".\";
                INIOperation.INIWriteValue(GlobalValues.ConfigFile, "Vup", "GameDirectory", GlobalValues.GameDir);
            }
        }
        public static void WriteConfig(string name, string value)
        {
            INIOperation.INIWriteValue(GlobalValues.ConfigFile, "Vup", name, value);
        }
        public static void LoadGameConfigFile()
        {
            GlobalValues.GameHostIP = INIOperation.INIGetStringValue(GlobalValues.GameDir + @".\config.ini", "General", "HostAddress", "");
            GlobalValues.NameInGame = INIOperation.INIGetStringValue(GlobalValues.GameDir + @".\config.ini", "General", "UserName", "");
            GlobalValues.NameInGame = Unicode2String(GlobalValues.NameInGame);
            GlobalValues.LocalVersion = INIOperation.INIGetStringValue(GlobalValues.GameDir + "\\version.ini", "Vup", "LocalVersion", "未知版本");
            Config2Coordinate();
        }
        public static void Config2Coordinate()
        {
            string GameWindow = INIOperation.INIGetStringValue(GlobalValues.GameDir + @".\config.ini", "General", "WindowSize", "@Size(1366 700)");
            string[] temp = GameWindow.Split(new char[] { '(', ' ', ')' });
            GlobalValues.GameWindowW = temp[1];
            GlobalValues.GameWindowH = temp[2];
        }
        public static void WriteGameConfigFile(string name, string value)
        {
            INIOperation.INIWriteValue(GlobalValues.GameDir + @".\config.ini", "General", name, value);
        }
        public static void GetRefresh()
        {
            Task.Run(INet.GetInformation).Wait();
            Task.Run(INet.GetNotice);
            Task.Run(INet.GetVersionCSV);
        }
        public static void ShowLauncherUpdate()
        {
            if (GlobalValues.LatestLauncherVersion != GlobalValues.LauncherVersion && !string.IsNullOrEmpty(GlobalValues.LatestLauncherVersion))
                if (IMessageBox.Show("检测到启动器本体有最新版本\n更新启动器能优化体验\n强烈建议更新\n是否进入官网查看？", "重要通知", "查看详情", "稍后再说"))
                    System.Diagnostics.Process.Start("https://" + GlobalValues.OfficialUrl.Replace("http://", string.Empty).Replace("https://", string.Empty));
        }
        public static void ReportPatchDownloadTimesPlus()
        {
            Task.Run(INet.ReportPatchDownloadTimesPlus);
        }
        public static void ReportMainDownloadTimesPlus()
        {
            Task.Run(INet.ReportMainDownloadTimesPlus);
        }
        public static void RefreshVersionState()
        {
            if (!GlobalValues.HaveNet) GlobalValues.VersionState = 0;
            else if (GlobalValues.LatestVersion == "未知版本") GlobalValues.VersionState = 1;
            else if (GlobalValues.LocalVersion == GlobalValues.LatestVersion) GlobalValues.VersionState = 2;
            else GlobalValues.VersionState = 3;
        }
        public static void ShowNotice()
        {
            if (GlobalValues.NoticeLatest.Contains("important")) LatestNotice();
            else if (GlobalValues.HaveNet && !(GlobalValues.NoticeLocal == "disable") && !(GlobalValues.NoticeLocal == GlobalValues.NoticeLatest) && !string.IsNullOrEmpty(GlobalValues.NoticeUrl)) LatestNotice();
        }
        public static void LatestNotice()
        {
            if (IMessageBox.Show(GlobalValues.NoticeContent, "游戏公告", "查看详情", "我知道了"))
                System.Diagnostics.Process.Start("https://" + GlobalValues.NoticeUrl.Replace("http://", string.Empty).Replace("https://", string.Empty));
            WriteConfig("Notice", GlobalValues.NoticeLatest);
        }

        public static string[][] ReadCSV(string csvtext)
        {
            string[] row = csvtext.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            string[][] result = new string[row.Length - 1][];
            for (int i = 0; i < row.Length - 1; i++)
            {
                result[i] = row[i].Split(',');
            }
            return result;
        }
        public static void FileExtract(string file)
        {
            string tempDir = GlobalValues.GameDir + @"\.temp";
            if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true);
            System.IO.Compression.ZipFile.ExtractToDirectory(file, tempDir, Encoding.GetEncoding("gbk"));
            string removelist = tempDir + @"\removelist.txt";
            if (File.Exists(removelist)) UpdateDel(removelist);
            CopyDir(tempDir, GlobalValues.GameDir);
            if (File.Exists(file)) File.Delete(file);
            if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true);
        }
        public static void CopyDir(string srcPath, string aimPath)
        {
            // 检查目标目录是否以目录分割字符结束如果不是则添加
            if (aimPath[aimPath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
            {
                aimPath += System.IO.Path.DirectorySeparatorChar;
            }
            // 判断目标目录是否存在如果不存在则新建
            if (!System.IO.Directory.Exists(aimPath))
            {
                System.IO.Directory.CreateDirectory(aimPath);
            }
            // 得到源目录的文件列表，该里面是包含文件以及目录路径的一个数组
            // 如果你指向copy目标文件下面的文件而不包含目录请使用下面的方法
            // string[] fileList = Directory.GetFiles（srcPath）；
            string[] fileList = System.IO.Directory.GetFileSystemEntries(srcPath);
            // 遍历所有的文件和目录
            foreach (string file in fileList)
            {
                // 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
                if (System.IO.Directory.Exists(file))
                {
                    CopyDir(file, aimPath + System.IO.Path.GetFileName(file));
                }
                // 否则直接Copy文件
                else
                {
                    System.IO.File.Copy(file, aimPath + System.IO.Path.GetFileName(file), true);
                }
            }
        }
        public static void UpdateDel(string file)
        {
            StreamReader sr = new StreamReader(file);
            while (!sr.EndOfStream)
            {
                DeleteFile(sr.ReadLine());
            }
            sr.Close();
            File.Delete(file);
        }
        public static void DeleteFile(string filename)
        {
            if (String.IsNullOrEmpty(filename)) return;
            if (File.Exists(GlobalValues.GameDir + '\\' + filename))
            {
                File.Delete(GlobalValues.GameDir + '\\' + filename);
            }
            else if (Directory.Exists(GlobalValues.GameDir + '\\' + filename))
            {
                Directory.Delete(GlobalValues.GameDir + '\\' + filename, true);
            }
        }
        public static string GetFileSize(long filesize)
        {
            if (filesize < 0) return "0";
            else if (filesize >= 1024 * 1024 * 1024) return string.Format("{0:0.00}GB", (double)filesize / (1024 * 1024 * 1024));
            else if (filesize >= 1024 * 1024) return string.Format("{0:0.00}MB", (double)filesize / (1024 * 1024));
            else if (filesize >= 1024) return string.Format("{0:0}KB", (double)filesize / 1024);
            else return string.Format("{0:0.00} bytes", filesize);
        }
        public static string GetFileMD5(string filepath)
        {
            FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
            int bufferSize = 1048576;
            byte[] buff = new byte[bufferSize];
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            md5.Initialize();
            long offset = 0;
            while (offset < fs.Length)
            {
                long readSize = bufferSize;
                if (offset + readSize > fs.Length)
                    readSize = fs.Length - offset;
                fs.Read(buff, 0, Convert.ToInt32(readSize));
                if (offset + readSize < fs.Length)
                    md5.TransformBlock(buff, 0, Convert.ToInt32(readSize), buff, 0);
                else
                    md5.TransformFinalBlock(buff, 0, Convert.ToInt32(readSize));
                offset += bufferSize;
            }
            if (offset >= fs.Length)
            {
                fs.Close();
                byte[] result = md5.Hash;
                md5.Clear();
                StringBuilder sb = new StringBuilder(32);
                for (int i = 0; i < result.Length; i++)
                    sb.Append(result[i].ToString("X2"));
                return sb.ToString();
            }
            else
            {
                fs.Close();
                return null;
            }
        }
        public static string String2Unicode(string source)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(source);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < bytes.Length; i += 2)
            {
                stringBuilder.AppendFormat("\\x{0}{1}", bytes[i + 1].ToString("x").PadLeft(2, '0'), bytes[i].ToString("x").PadLeft(2, '0'));
            }
            return stringBuilder.ToString();
        }
        public static string Unicode2String(string source)
        {
            return new Regex(@"\\x([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(
                         source, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));
        }
        public static bool CloseProc(string ProcName)
        {
            bool result = false;
            System.Collections.ArrayList procList = new System.Collections.ArrayList();
            string tempName = "";

            foreach (System.Diagnostics.Process thisProc in System.Diagnostics.Process.GetProcesses())
            {
                tempName = thisProc.ProcessName;
                procList.Add(tempName);
                if (tempName == ProcName)
                {
                    if (!thisProc.CloseMainWindow())
                        thisProc.Kill();
                    result = true;
                }
            }
            return result;
        }

    }
}
